/////////////////////////////////////////////////////////////
//                      C++ Serialization                  //
//                                                         //
//  copyright:   (c) 2011 CPPS                             //
//  authors:     Hikki-Kun                                 //
//  mail:        glrenderable@gmail.com                    //
//                                                         //
//  This program is made available under the terms of      //
//  the MIT License.                                       //
/////////////////////////////////////////////////////////////
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF  //
//  ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED//
//  TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A    //
//  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT    //
//  SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR   //
//  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   //
//  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,   //
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE   //
//  OR OTHER DEALINGS IN THE SOFTWARE.                     //
/////////////////////////////////////////////////////////////
#ifndef ELLSER_TYPE_LIST_HPP
#define ELLSER_TYPE_LIST_HPP

//
//  `EmptyList' is terminal for `TypeList'
// 
struct EmptyList {};

//
//  `TypeList' contains potentially 
//  infinity list of types
//
template <typename H, typename T>
struct TypeList 
{
  typedef typename H Head;
  typedef typename T Tail;
};


//
//  Compute length of `TypeList' structure 
//  by recursive expansion
//
template <typename TypeList> 
struct Length;


template <typename Head, typename Tail>
struct Length<TypeList<Head, Tail> > 
{
  enum { value = 1 + Length<Tail>::value };
};


template <>
struct Length<EmptyList> 
{
  enum { value = 0 };
};


//
//  Check whether `TypeList' contains a 
//
template <typename TypeList, typename Type>
struct Contains;


template <
    typename Head, 
    typename Tail, 
    typename Type
>
struct Contains<TypeList<Head, Tail>, Type> 
{
  enum { value = false 
      || Contains<Tail, Type>::value };
};


template <typename Type, typename Tail>
struct Contains<TypeList<Type, Tail>, Type> 
{
  enum { value = true };
};

template <typename Type>
struct Contains<EmptyList, Type> {
  enum { value = false };
};

#endif // end file guardian